package seggio;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

public class Seggio extends Thread {

    //private static ServerSocket seggio;
    //---
    public static final int PORTA_CABINA = 10000;
    //---
    static String scheda;
    public static int id;
    private String ipCabinaLibera;
    public static String schedaSenato;
    public static String schedaCamera;
    public static String referendum;
    //---
    //private static DOMxml domXMLCabina;
    //private static DOMxml domXMLSeggio;
    //---
    //private StartConfigSeggio startConfigSeggio;
    private InviaInCabina inviaInCab;
    String ipLibero = null;
    public DOMxml x;
    private HashMap<String, Boolean> statoCab;
    //public Semaphore s;
    int ID;
    String REGIONE;
    String IP_SEGGIO;
    int PORT_SEGGIO;
    String IP_INTERNO;
    int PORT_INTERNO;
    private Object mutex = 1;

    public Seggio(int ID, String REGIONE, String IP_SEGGIO, int PORT_SEGGIO, String IP_INTERNO, int PORT_INTERNO) throws Exception {

        //setto variabili che serviranno al controllore del votante
        this.ID = ID;
        this.REGIONE = REGIONE;
        this.IP_SEGGIO = IP_SEGGIO;
        this.PORT_SEGGIO = PORT_SEGGIO;
        this.IP_INTERNO = IP_INTERNO;
        this.PORT_INTERNO = PORT_INTERNO;                 
        
        
        //inizializzo la mappa con tutte le cabine libere
        statoCab = new HashMap<String,Boolean>();
        System.out.println("lista cabine:");
        HashMap resMap = riempiHashMapOnStart(statoCab);
        System.out.println("stampo la hashTable piena:");
        System.out.println(statoCab);
        
        this.ipCabinaLibera = getPrimoIpLibero(statoCab);
        
    }

    //true = LIBERA  || false = OCCUPATA   
    public final HashMap riempiHashMapOnStart(HashMap m) {
        DOMxml domXMLCabina = new DOMxml("src/config/configSeggio.xml", "cabina");
        //riempi la hash map tutta a true = tutte le cabine sono disponibili alla crerazione del seggio
        ArrayList<String> listaCabine = domXMLCabina.getIPCabina();
        // "per ogni Stringa cabina in listaCabine"
        // System.out.println(listaCabine);
        for (String cabina : listaCabine) {
            statoCab.put(cabina, true);
        }
        return statoCab;
    }

    public HashMap setHashMap() {
        return statoCab;
    }
    //ritorna null se non trova cabine libere

    public final String getPrimoIpLibero(HashMap<String, Boolean> hm) {

        Set list = hm.keySet();
        Iterator iter = list.iterator();
        String key = null;
        Boolean value = true;
        while (iter.hasNext()) {
            key = (String) iter.next();
            value = (Boolean) hm.get(key);
            //true cabina LIBERA --- false cabina OCCUPATA
            if (value != true) {
                //return null;
            } else {
                ipLibero = key.toString();
            }
        }
        return ipLibero;
    }

    //cambia lo sato della cabina cercando nella hashMap a la chiave e modifo il valore
    public void setStatoCabina(String ip, Boolean s) {
        Set list = statoCab.keySet();
        Iterator iter = list.iterator();
        String key = null;
        Boolean value = true;
        while (iter.hasNext()) {
            key = (String) iter.next();
            if (key.equals(ip)) {
                value = s;
                statoCab.remove(key);
                statoCab.put(key, value);
            }
        }
    }

    public static String getScheda() {
        return scheda;
    }

    private void creaRappresentateSeggio(String IP_INTERNO, int PORT_INTERNO) throws IOException {
        
        inviaInCab = new InviaInCabina(ipCabinaLibera, PORTA_CABINA);
        
        InputStream i = System.in;
        InputStreamReader is = new InputStreamReader(i);
        BufferedReader br = new BufferedReader(is);

        //creo un rappresentate del seggio che controlla l'utente
        String nome = RappresentanteSeggio.richiediNome();
        String cognome = RappresentanteSeggio.richiediCognome();
        String dn = RappresentanteSeggio.richiediDataNascita();
        String cf = RappresentanteSeggio.richiediCfiscale();

        ControlloVotante cv = new ControlloVotante(nome, cognome, dn, cf);

        if (cv.controllaVotanteSeInLista(cf)) {

            System.out.println("ok è presente nella lista, controllo l'età");

            if (cv.controllaVotoPerSenato()) {

                System.out.println("puoi votare per il senato");
                System.out.println("hai il diritto di votare per CAMERA, SENATO, REFERENDUM");

                System.out.println("voi votare per SENATO ? si/no");
                String rispSenato = br.readLine();

                System.out.println("voi votare per la CAMERA ? si/no");
                String rispCamera = br.readLine();

                System.out.println("voi votare per il REFERENDUM ? si/no");
                String rispReferendum = br.readLine();
                
                System.out.println("imposto la cabina "+ipCabinaLibera+" su Occupata");                
                setStatoCabina(ipCabinaLibera,false);
                System.out.println("cabine libere attualmente: ");
                System.out.println(statoCab);
                
                if ("si".equals(rispSenato)) {
                    schedaSenato = RichiediSchede.getSchedaEle("SENATO", IP_INTERNO, PORT_INTERNO);
                    System.out.println("scheda del SENATO ricevuta dal server interno");
                    System.out.println("scheda SENATO : " + schedaSenato);
                    System.out.println("invio la scheda del SENATO alla cabina : " + ipCabinaLibera + " : " + PORTA_CABINA + " scheda : " + schedaSenato);
                    inviaInCab.sendSchedaSenato(schedaSenato);
                }

                if ("si".equals(rispCamera)) {
                    schedaCamera = RichiediSchede.getSchedaEle("CAMERA", IP_INTERNO, PORT_INTERNO);
                    System.out.println("scheda della CAMERA ricevuta dal server interno");
                    System.out.println("scheda CAMERA : " + schedaCamera);
                    System.out.println("invio la scheda del CAMERA alla cabina : " + ipCabinaLibera + " : " + PORTA_CABINA + " scheda : " + schedaCamera);
                    //inviaInCab = new InviaInCabina(ipCabinaLibera, PORTA_CABINA);
                    inviaInCab.sendSchedaCamera(schedaCamera);
                }

                if ("si".equals(rispReferendum)) {
                    System.out.println(RichiediSchede.getSchedaEle("REFERENDUM", IP_INTERNO, PORT_INTERNO));
                    referendum = RichiediSchede.getSchedaEle("REFERENDUM", IP_INTERNO, PORT_INTERNO);
                    //inviaInCab = new InviaInCabina(ipCabinaLibera, PORTA_CABINA);
                    inviaInCab.sendSchedaReferendum(referendum);
                }
                
                //inviaInCab = new InviaInCabina(ipCabinaLibera, PORTA_CABINA);
                System.out.println("invio il tag di fine invio schede alla cabina, in modo che possa cominciare la votazione");
                inviaInCab.sendStatoDiFine();

            } else {

                System.out.println("puoi votare solo per la CAMERA e REFERENDUM");

                System.out.println("voi votare per la CAMERA ? si/no");
                String rispCamera = br.readLine();
                if ("si".equals(rispCamera)) {
                    System.out.println(RichiediSchede.getSchedaEle("CAMERA", IP_INTERNO, PORT_INTERNO));
                    schedaCamera = RichiediSchede.getSchedaEle("CAMERA", IP_INTERNO, PORT_INTERNO);
                    //inviaInCab = new InviaInCabina(ipCabinaLibera, PORTA_CABINA);
                    inviaInCab.sendSchedaCamera(schedaCamera);
                }

                System.out.println("voi votare per il REFERENDUM ? si/no");
                String rispReferendum = br.readLine();
                if ("si".equals(rispReferendum)) {
                    System.out.println(RichiediSchede.getSchedaEle("REFERENDUM", IP_INTERNO, PORT_INTERNO));
                    referendum = RichiediSchede.getSchedaEle("REFERENDUM", IP_INTERNO, PORT_INTERNO);
                    //inviaInCab = new InviaInCabina(ipCabinaLibera, PORTA_CABINA);
                    inviaInCab.sendSchedaReferendum(referendum);
                }
                
                System.out.println("invio il tag di fine invio schede alla cabina, in modo che possa cominciare la votazione");
                inviaInCab.sendStatoDiFine();
            }
            
        } else {
            System.out.println("non è presente in lista");
        }
        //this.start();
    }

    private synchronized Object getMutex() {
        return mutex;
    }

    public void vota() throws InterruptedException, IOException {
        //prendo la mutua esclusione per il processo che ha richiesto di votare
            
        //synchronized (getMutex()) {
            //s.acquire();
            //controllo che vi sia una cbina libera
            System.out.println("");
            System.out.println("==============================");
            System.out.println("============START=============");
            System.out.println("==============================");
            System.out.println("");
            System.out.println(statoCab);
            String ip = getPrimoIpLibero(statoCab);
            
            //socket = new Socket(ipCabinaLibera, 10000); 
            
            //non ho trovato una cabina disponibile
            if (ip == null) {
                //condizione di attesa del sulla coda del semaforo, si sblocca quando ricevo s.notify()
                System.out.println("---nessuna cabina libera---");
                getMutex().wait();
            }
            //comunica IPseggio alla cabina e Porta
            //StartConfigSeggio scs = new StartConfigSeggio();            
            //scs.comunicaIPSeggioAllaCabina(ipCabinaLibera, PORTA_CABINA);
            //scs.comunicaPORTASeggioAllaCabina(ipCabinaLibera, PORTA_CABINA);
            //richiedo i dati al cliente
            System.out.println("");
            //System.out.println(ip);
            
            creaRappresentateSeggio(IP_INTERNO, PORT_INTERNO);
            
            GestoreRichieste grV = new GestoreRichieste(ip);
            //lancio il thread gestore cabina
            grV.start();           

            //DOMxml domXMLSeggio = new DOMxml("src/config/configSeggio.xml", "seggio");
            //ServerSocket seggio = new ServerSocket(domXMLSeggio.getPortaSeggio());
            //creo un ascoltatore sulla cabina

            //getMutex().notify();

        //}
        
        
    }

    public static void main(String argv[]) throws Exception {

        DOMxml domXMLSeggio = new DOMxml("src/config/configSeggio.xml", "seggio");
        
        StartConfigSeggio scs = new StartConfigSeggio();
        //Registro il seggio appena creato sul server interno
        scs.registrazioneSeggio(domXMLSeggio.getIdSeggio(), domXMLSeggio.getRegione(), domXMLSeggio.getIPSeggio(), domXMLSeggio.getPortaSeggio(), domXMLSeggio.getIPInterno(), domXMLSeggio.getPortaInterno());

        //crea un nuovo seggio
        Seggio sSeggio = new Seggio(domXMLSeggio.getIdSeggio(), domXMLSeggio.getRegione(), domXMLSeggio.getIPSeggio(), domXMLSeggio.getPortaSeggio(), domXMLSeggio.getIPInterno(), domXMLSeggio.getPortaInterno());
        while (true) {
            sSeggio.vota();
            sleep(5000);
        }
    }
}